// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RibbonMergeRegionAdapter.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Enables use of a Ribbon control as a Prism region.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Client.Common.Adapters
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;

    using Fluent;

    using Microsoft.Practices.Prism.Regions;

    /// <summary>
    /// Enables use of a Ribbon control as a Prism region.
    /// </summary>
    /// <remarks> See Developer's Guide to Microsoft Prism (Ver. 4), p. 189.</remarks>
    public class RibbonMergeRegionAdapter : RegionAdapterBase<RibbonTabItem>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RibbonMergeRegionAdapter"/> class.
        /// </summary>
        /// <param name="behaviorFactory">
        /// Allows the registration of the default set of RegionBehaviors.
        /// </param>
        public RibbonMergeRegionAdapter(IRegionBehaviorFactory behaviorFactory)
            : base(behaviorFactory)
        {
        }

        /// <summary>
        /// Adapts a WPF control to serve as a Prism IRegion.
        /// </summary>
        /// <param name="region">The new region being used.</param>
        /// <param name="regionTarget">The WPF control to adapt.</param>
        protected override void Adapt(IRegion region, RibbonTabItem regionTarget)
        {
            region.Views.CollectionChanged += (sender, e) =>
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        foreach (FrameworkElement element in e.NewItems)
                        {
                            var ribbonItemsControl = element as RibbonTabItem;
                            if (ribbonItemsControl != null)
                            {
                                for (int j = ribbonItemsControl.Groups.Count - 1; j >= 0; j--)
                                {
                                    RibbonGroupBox group = ribbonItemsControl.Groups[j];
                                    ribbonItemsControl.Groups.RemoveAt(j);
                                    var existingGroup = regionTarget.Groups.FirstOrDefault(
                                        g => g.Header == group.Header);
                                    if (existingGroup != null)
                                    {
                                        int index = existingGroup.Items.Count;
                                        for (int i = group.Items.Count - 1; i >= 0; i--)
                                        {
                                            var item = group.Items[i] as Control;
                                            group.Items.RemoveAt(i);

                                            var value = item.GetValue(Helpers.IndexHelper.IndexProperty);
                                            if (value != null)
                                            {
                                                int itemIndex = GetIndex(value, existingGroup.Items);
                                                existingGroup.Items.Insert(itemIndex, item);
                                                Console.WriteLine(
                                                    string.Format(
                                                        "Inserting control {1} at index {0}",
                                                        itemIndex,
                                                        item is SplitButton
                                                            ? ((SplitButton)item).Header
                                                            : ((Fluent.Button)item).Header));
                                            }
                                            else
                                            {
                                                existingGroup.Items.Add(item);
                                                Console.WriteLine(
                                                    string.Format(
                                                        "Added control {1} at index {0}",
                                                        existingGroup.Items.Count,
                                                        item is SplitButton
                                                            ? ((SplitButton)item).Header
                                                            : ((Fluent.Button)item).Header));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        var value = group.GetValue(Helpers.IndexHelper.IndexProperty);
                                        if (value != null)
                                        {
                                            int index = GetIndex(value, regionTarget.Groups);
                                            regionTarget.Groups.Insert(index, group);

                                            int controlInsertIndex = int.Parse(value.ToString());
                                            int insertIndex = -1;
                                            int i = 0;
                                            foreach (FrameworkElement control in regionTarget.Groups)
                                            {
                                                var itemIndex = control.GetValue(Helpers.IndexHelper.IndexProperty);
                                                if (itemIndex != null)
                                                {
                                                    int itemIndexValue = int.Parse(itemIndex.ToString());
                                                    if (itemIndexValue > controlInsertIndex)
                                                    {
                                                        insertIndex = i;
                                                        break;
                                                    }

                                                    i++;
                                                }
                                            }

                                            if (insertIndex >= 0 && insertIndex < regionTarget.Groups.Count)
                                            {
                                                regionTarget.Groups.Insert(insertIndex, element as RibbonGroupBox);
                                                continue;
                                            }
                                        }

                                        regionTarget.Groups.Add(group);
                                    }
                                }
                            }
                        }

                        break;

                    case NotifyCollectionChangedAction.Remove:
                        foreach (UIElement elementLoopVariable in e.OldItems)
                        {
                            var element = elementLoopVariable;
                            var group = element as RibbonGroupBox;
                            if (group != null)
                            {
                                if (regionTarget.Groups.Contains(element as RibbonGroupBox))
                                {
                                    regionTarget.Groups.Remove(element as RibbonGroupBox);
                                }
                            }
                        }

                        break;
                }
            };
        }

        /// <summary>
        /// Creates the region.
        /// </summary>
        /// <returns>Region object</returns>
        protected override IRegion CreateRegion()
        {
            return new AllActiveRegion();
        }

        /// <summary>
        /// Gets the index.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="collection">Type of collection objects</param>
        /// <returns>Index to insert item at</returns>
        private static int GetIndex(object value, ItemCollection collection)
        {
            int index = int.Parse(value.ToString()) - 1;
            if (index < 0)
            {
                index = 0;
            }

            foreach (Control control in collection)
            {
                var indexValue = control.GetValue(Helpers.IndexHelper.IndexProperty);
                if (indexValue != null)
                {
                    int controlIndex = int.Parse(indexValue.ToString());
                    if (index >= controlIndex)
                    {
                        index = controlIndex;
                        break;
                    }
                }
            }

            if (index > collection.Count)
            {
                index = collection.Count;
            }

            return index;
        }

        /// <summary>
        /// Gets the index.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="collection">Type of collection objects</param>
        /// <returns>Index to insert item at</returns>
        private static int GetIndex(object value, IEnumerable<Control> collection)
        {
            int index = int.Parse(value.ToString()) - 1;
            if (index < 0)
            {
                index = 0;
            }

            foreach (var control in collection)
            {
                var indexValue = control.GetValue(Helpers.IndexHelper.IndexProperty);
                if (indexValue != null)
                {
                    int controlIndex = int.Parse(indexValue.ToString());
                    if (index >= controlIndex)
                    {
                        index = controlIndex;
                        break;
                    }
                }
            }

            if (index > collection.Count())
            {
                index = collection.Count();
            }

            return index;
        }
    }
}